package com.huawei.codearts.tools.aop;

import com.huawei.codearts.dao.RedisDao;
import com.huawei.codearts.entity.UserDetails;
import com.huawei.codearts.tools.utils.HeaderUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
//import org.springframework.security.core.userdetails.UserDetails;

import java.security.MessageDigest;
import java.util.*;

/**
 * 用户验证 AOP
 */

@Slf4j
@Aspect
@Component
public class LoginAspect {

    @Autowired
    private RedisDao redisClient;

//    @Pointcut("execution(* com.huawei.codearts.service.UserServiceImpl.getUserById(..))")
//    @Pointcut("execution(* com.huawei.codearts.service.*.*(..))")
    @Pointcut("execution(* com.huawei.codearts.controller.*.*(..))")
    public void beforePointcut() {}

    // 测试只针对接口 /rate/limiter/uid
    @Pointcut("execution(public * com.huawei.codearts.controller.TestController.*uid(..))")
    public void verify() {}

    @Pointcut("execution(public * com.huawei.codearts.controller.Test*.*(..))"+
            "&& !execution(public * com.huawei.codearts.controller.TestController.*(..))")
    public void test() {}  /** 开发阶段使用test 方便测试 */

    @Before("verify()")  // 前置通知
    public void doBefore(JoinPoint joinPoint) throws Exception {
        // 获取信息头里的token
        String token = HeaderUtils.get("token");
        // 获取多个key值
//        Map<String, String> hmap = HeaderUtils.get("token", "auth");
//        log.info("LoginAspect hmap.token... {}, hmap.auth... {}", hmap.get("token"), hmap.get("auth"));
        // 参数数组
        Object[] args = joinPoint.getArgs();
//        String token = (String) args[0];
        log.info("LoginAspect doBefore路径: {}, token: {}", args, token);
        // 类名
        String className = joinPoint.getTarget().getClass().getSimpleName();
        //方法名
        String methodName = joinPoint.getSignature().getName();
        log.info("LoginAspect className: {}, methodName: {}, args: {}", className, methodName, args);

        // 验证登录信息
        if (!validateUser(token, className, methodName)) {
            throw new IllegalArgumentException("Invalid token");
        }
    }

    private boolean validateUser(String token, String className, String methodName) throws Exception {

        if (Objects.equals(token, "") || Objects.equals(token, null)) {
            throw new IllegalArgumentException("token is empty");
        }

        // 创建MD5消息摘要对象
        MessageDigest md = MessageDigest.getInstance("MD5");
        // 计算消息的摘要
        byte[] digest = md.digest(token.getBytes());
        // 将摘要转换为十六进制字符串
        String hexString = bytesToHex(digest);
        System.out.println("MD5 Digest: " + hexString);

        String tokenValue = redisClient.get(hexString);
        tokenValue = "正式使用时删除此行";  // 测试使用
        if (tokenValue != null) {
            // 解析token 并 延长token续期

            // 加载用户详情
//            UserDetails userDetails = new org.springframework.security.core.userdetails.User(
//                    "username",
//                    "password",
//                    new ArrayList<>() // 用户的权限
//            );
            // 加载用户详情 自定义实体
            UserDetails userDetails = new UserDetails(
                    96L,
                    "username-oop",
                    new ArrayList<>() // 用户的权限
            );

            // 创建 Authentication 对象
            Authentication authentication = new UsernamePasswordAuthenticationToken(
                    userDetails, null, userDetails.getAuthorities());

            // 将 Authentication 对象保存到 SecurityContextHolder 中
            SecurityContextHolder.getContext().setAuthentication(authentication);

//            // 获取当前的 SecurityContext
//            SecurityContext context = SecurityContextHolder.createEmptyContext();
//            context.setAuthentication(authentication);
//
//            // 将 SecurityContext 存储在 SecurityContextHolder 中
//            SecurityContextHolder.setContext(context);

            return true;
        }

        return false;
    }

    public static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }

}